import { toRaw, unref } from 'vue';
import { defineStore } from 'pinia';
import { RouteRecordRaw } from 'vue-router';
import { store } from '@/store';
import { asyncRoutes, constantRouter } from '@/router/index';
// import { generatorDynamicRouter } from '@/router/generator-routers';
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
import { isArray } from '@/utils/is/index';
// import { getAppEnvConfig } from '@/utils/env';
import {
  DashboardRoute,
  // SettingRoute
} from '@/router/init';
import { useUserStore } from '@/store/modules/user';
import { useProjectSettingStore } from '@/store/modules/projectSetting';

import config from '@/config';



const { VUE_APP_ALLROUTERMENU, VUE_APP_SYSTEM_PREFIX, VUE_APP_NAME } = config;

export interface IAsyncRouteState {
  menus: RouteRecordRaw[];
  routers: any[];
  addRouters: any[];
  keepAliveComponents: string[];
  isDynamicAddedRoute: boolean;
}

const getPowers = (list: []): any => {
  let powersList = [];

  if (!list) return [];

  for (const item of list) {
    const { menuCode = '', children = [] } = item;

    if (menuCode) {
      powersList.push(menuCode);
    }

    if (children && children.length) {
      const childList = getPowers(children as any);

      powersList = powersList.concat(childList);
    }
  }

  return powersList;
};

/**
 * Use meta.authCode to determine if the current route has permission
 * @param powers
 * @param route
 */
const hasAuthCode = (powers, route) => {
  return (
    route.meta &&
    route.meta.authCode &&
    powers.some((power) => equalAuthCode(route.meta.authCode, power))
  );
};

/**
 * Use meta.authCode to determine if the authCode contain power
 * @param powers
 * @param route
 */
const equalAuthCode = (authCode, power) => {
  if (isArray(authCode)) return authCode.includes(power);

  return `${authCode}` === power;
};

/**
 * Use meta.authCode to determine if the current user has permission
 * @param powers
 * @param route
 */
const hasPermission = (powers, route) => {
  if (route.meta && route.meta.authCode) {
    const button = route.meta.button || [];

    if (route.children) {
      return route.children.some((item) => hasAuthCode(powers, item));
    }

    return (
      powers.some((power) => equalAuthCode(route.meta.authCode, power)) ||
      button.some((item) => powers.includes(item.name))
    );
  } else {
    return false;
  }
};

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param powers
 */
export const filterAsyncRoutes = (routes, powers) => {
  const routerList: any = [];

  routes.forEach((route: any) => {
    const tmp: any = { ...route };

    if (hasPermission(powers, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, powers);
      }

      // tmp.meta.moduleName = moduleName;

      routerList.push(tmp as any);
    }
  });

  return routerList;
};

export const useAsyncRouteStore = defineStore({
  id: 'app-async-route',
  state: (): IAsyncRouteState => ({
    menus: [],
    routers: constantRouter,
    addRouters: [],
    keepAliveComponents: [],
    // Whether the route has been dynamically added
    isDynamicAddedRoute: false,
  }),
  getters: {
    getMenus(): RouteRecordRaw[] {
      return this.menus;
    },
    getIsDynamicAddedRoute(): boolean {
      return this.isDynamicAddedRoute;
    },
  },
  actions: {
    getRouters() {
      return toRaw(this.addRouters);
    },
    setDynamicAddedRoute(added: boolean) {
      this.isDynamicAddedRoute = added;
    },
    // 设置动态路由
    setRouters(routers) {
      this.addRouters = routers;
      this.routers = constantRouter.concat(routers);
    },
    setMenus(menus) {
      // 设置动态路由
      this.menus = menus;
    },
    setKeepAliveComponents(compNames) {
      // 设置需要缓存的组件
      this.keepAliveComponents = compNames;
    },
    async generateRoutes(data: any) {
      const userStore = useUserStore();

      const { powers:powersList = [] } = data;

      // const powersList = getPowers(menuList) || [];

      let accessedRouters: any = [];

      const { getPermissionMenu } = useProjectSetting();

      const permissionMenu = unref(getPermissionMenu);

      accessedRouters.push(
        ...[
          DashboardRoute,
          // SettingRoute
        ]
      );

      if (permissionMenu) {
        // 校验菜单
        if (!powersList.length) {
          powersList.push(`dashboard`);
          // powersList.push(`${getAppEnvConfig().VITE_GLOB_SYSTEM_PREFIX}-dashboard`);
        } else {
          accessedRouters = [...accessedRouters, ...filterAsyncRoutes(asyncRoutes, powersList)];
        }
        // accessedRouters.push(asyncRoutes[asyncRoutes.length - 1] as any);
      } else {
        accessedRouters = [...accessedRouters, ...asyncRoutes];
      }

      userStore.setPowers(powersList);

      this.setRouters(accessedRouters);

      this.setMenus(accessedRouters);

      return toRaw(accessedRouters);
    },
    filtergenerateRoutes(powersList: any = []) {
      const isPermission =
        VUE_APP_ALLROUTERMENU === 'true' &&
        !(powersList.length === 1 && powersList[0] === '*:*');

      let accessedRouters: any = [];

      accessedRouters.push(DashboardRoute);

      console.log(isPermission);

      if (isPermission) {
        // 校验菜单
        if (!powersList.length) {
          powersList.push(`${VUE_APP_SYSTEM_PREFIX}-${VUE_APP_NAME}-dashboard`);
        } else {
          accessedRouters = [...accessedRouters, ...filterAsyncRoutes(asyncRoutes, powersList)];
        }
        // accessedRouters.push(asyncRoutes[asyncRoutes.length - 1] as any);
      } else {
        const projectStore = useProjectSettingStore();

        projectStore.setPermissionCheck(false);

        accessedRouters = [...accessedRouters, ...asyncRoutes];
      }

      this.setRouters(accessedRouters);

      this.setMenus(accessedRouters);

      return toRaw(accessedRouters);
    },
  },
});

// Need to be used outside the setup
export function useAsyncRouteStoreWidthOut() {
  return useAsyncRouteStore(store);
}
